<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

<script>
var jsonrpc = function(method, params, callback, scope) {
	var xhr = new XMLHttpRequest;
	xhr.open('POST', '/jsrun', true);
	//xhr.setRequestHeader('Connection', 'close');
	xhr.onreadystatechange = function(){
		if (xhr.readyState != 4) return;
		if (callback) {
			var x = JSON.parse(xhr.responseText);
			callback.call(scope || this, x.result);
		}
	};
	var x = { method: method, params: params };
	xhr.send(JSON.stringify(x));
	//xhr.onreadystatechange();
};

var test = function() {
	jsonrpc('get_counter', null, function(x) {
		alert(x);
	});
};


//var lock = false;




var mklate = function(delay){
	var mkapply = function(f,th,args){ return function(){ return f.apply(th,args) } };
	var defined = function(x){ return x!==undefined };
	var is_function = function(x){ return x instanceof Function };
	var f, timer;
	var locked;
	return function(d,func){
		if(is_function(d))func=d,d=undefined;
		if(!is_function(func))func=function(){};
		return function(/*...*/){
			if(locked)return;
			f=mkapply(func,this,arguments);
			if(defined(delay)&&!defined(d))d=delay;
			if(defined(d)&&timer) window.clearTimeout(timer), timer=null;
			if(!timer) timer=window.setTimeout(function(){timer=null,f()},d||100);
		}
	};
};		


(function() {
	var x0, y0, target;
	var dirty = false;
	var n = 0;

	var update_timer;
	var count = 0;

	var callback = function(xx){
		var div, pos;
		if (update_timer) {
			window.clearTimeout(update_timer);
			update_timer = null;
		}		
		var obj, id, x, y, x0, y0, dr;
		for (var i = 0; i < xx.length; ++i) {
			obj = xx[i];
			id = obj[0];
			x  = obj[1];
			y  = obj[2];
			div = document.getElementById(id);
			if (!div) {
				div = document.createElement('div');
				div.id = id;
				div.style.cssText = 'position:absolute;width:50px;height:50px;zbackground-color:red;background:url(http://www.dom-toys.ru/published/publicdata/LAREDOUTE/attachments/SC/products_pictures/cherepaha.gif) no-repeat';
				document.body.appendChild(div);
			}
			if (!div.locked) {
				dx = x - div.offsetLeft;
				dy = y - div.offsetTop;
				//dr = Math.sqrt(dx * dx + dy * dy) + 1;
				$(div).stop(true, true).animate({ left: x, top: y }, 100);
				//div.style.left = x + 'px'; div.style.top = y + 'px';
				
				//div.style.backgroundColor = 'blue';
			}
		}
		++count;
		var c = count;
		update_timer = window.setTimeout(function(){
			update_timer = null;
			jsonrpc('get_objects', ++n, callback);
		}, 150);
	};


	var update_callback = function(){
		window.setTimeout(function() {
			var xx = [], yy = [];
			$('.dirty').each(function(){
				xx[xx.length] = this;
				yy[yy.length] = [this.id, this.offsetLeft, this.offsetTop];
				$(this).removeClass('dirty');
			});
			if (!yy.length) {
				update_callback();
				return;
			}
			if (update_timer) {
				window.clearTimeout(update_timer);
				update_timer = null;
			}
			jsonrpc('update_objects', yy, function(xx){
				for(var i = 0; i < xx.length; ++i)
					xx.locked = false;
				callback(xx);
				update_callback();
			});
		}, 50);
	};

	
	jsonrpc('get_objects', null, callback);
	update_callback();

	/*
	var sync = function(){
		if (!target) return;
	};
	var late_sync = mklate(50)(sync);
	*/

	
	var start = function(e) {
		if (e.button != 0) return;
		if (!e.target.id) return;
		$(target).stop(true);
		
		target = e.target.cloneNode(false);
		document.body.appendChild(target);
		target.style.opacity = '0.5';
		
				
		//target = e.target;
		//target.locked = true;
		x0 = target.offsetLeft - e.screenX;
		y0 = target.offsetTop - e.screenY;
		document.addEventListener('mousemove', move, false);
		document.addEventListener('mouseup', done, false);

		//$(target).addClass('locked');
		//target.style.backgroundColor = 'red';
		target.style.background = 'none';
		target.style.border = '1px solid black';
		
		//lock = true;
		e.stopPropagation();
		e.preventDefault();
		return false;
	};

	var done = function(e) {
		//sync();
		//target = null;
		target.locked = false;
		//lock = false;
		//$(target).removeClass('locked');
		target.parentNode.removeChild(target);
		
		document.removeEventListener('mousemove', move, false);
		document.removeEventListener('mouseup', done, false);
	};


	var move = function(e) {
		target.style.left = (e.screenX + x0) + 'px';
		target.style.top = (e.screenY + y0) + 'px';
		//jsonrpc('update_object', [target.id, target.offsetLeft, target.offsetTop], callback);
		$(target).addClass('dirty');
		//late_sync();
		//sync();
	};

	document.addEventListener('mousedown', start, false);
})();

</script>

















